package com.qire.manhua.model.viewModel.impl;

import android.os.CountDownTimer;
import android.view.View;
import android.widget.EditText;

import com.qire.antscore.annotation.PropertyObserve;
import com.qire.antsrouter.AntsRouter;
import com.qire.common.basic.ObjectUtil;
import com.qire.common.basic.StringUtil;
import com.qire.common.collect.ListUtil;
import com.qire.common.constant.Navigation;
import com.qire.common.model.entity.UserEntity;
import com.qire.common.support.DialogFastBuildUtil;
import com.qire.common.support.base.BaseViewModel;
import com.qire.common.utils.CountDownTimerBuilder;
import com.qire.common.utils.ToastHelper;
import com.qire.manhua.R;
import com.qire.manhua.dal.service.AccountBindGuideService;
import com.qire.manhua.databinding.ActivityAccountBindGuideBinding;
import com.qire.manhua.model.enumeration.AccountBusinessPanelLayout;
import com.qire.manhua.model.viewModel.IAccountBindGuideViewModel;

import net.yslibrary.android.keyboardvisibilityevent.util.UIUtil;

import java.util.Arrays;
import java.util.Stack;
import java.util.concurrent.TimeUnit;

public class AccountBindGuideViewModel extends BaseViewModel<IAccountBindGuideViewModel> {

    private AccountBindGuideService bindGuideService = new AccountBindGuideService(this);

    /** 是否是首次号码验证*/
    private boolean isNewPhoneVerify = false;
    /** 是否是人工服务流程*/
    private boolean isArtificialService = false;

    private ActivityAccountBindGuideBinding viewDataBinder;

    //region    #附加管理 begin
    /** 附加属性绑定 */
    public void onAddition(ActivityAccountBindGuideBinding viewDataBinder) {
        this.viewDataBinder = viewDataBinder;
        initPanelLayout();
    }

    /**
     * 清理函数，在Activity退出时，ViewModel生命周期到期会被回收，调用该事件，
     * 页面由于切换、横竖屏转换、内存回收等情况并不会影响到ViewModel的生命周期。
     */
    @Override
    protected void onCleared() {
        super.onCleared();
        this.bindGuideService = null;
        this.viewDataBinder = null;
    }
    //endregion #附加管理 end

    //region    #业务与数据 begin
    /** 手机号码有效验证 */
    public boolean phoneIsValid(String phone) {
        return StringUtil.notEmpty(phone) && StringUtil.isMobile(phone);
    }

    /** 申诉信息有效验证 */
    public boolean appealInfoIsValid(String contactPhone, String contactTime, String note) {
        if(StringUtil.isEmpty(contactPhone)/* || !StringUtil.isMobile(contactPhone)*/)
            return false;
        if(StringUtil.isEmpty(contactTime))
            return false;
        if(StringUtil.isEmpty(note))
            return false;
        return true;
    }

    public void setIsArtificialService(boolean isArtificialService) {
        this.isArtificialService = isArtificialService;
    }

    public boolean isArtificialService() {
        return isArtificialService;
    }

    public void setIsNewPhoneVerify(boolean isNewPhoneVerify) {
        this.isNewPhoneVerify = isNewPhoneVerify;
    }

    public boolean isNewPhoneVerify() {
        return isNewPhoneVerify;
    }

    public String bindPhoneNumber() {
        String mobile = isNewPhoneVerify ? getToValue("newPhone") : UserEntity.self.getMobile();
        return StringUtil.defValue(mobile, "");
    }

    /** 验证新号码是否有效：是否存在该账户 */
    public void authNewPhoneNumber() {
        String newPhone = getToValue("newPhone", "");
        if(phoneIsValid(newPhone)) {
            bindGuideService.authPhoneNumberBy(newPhone);
        } else {
            ToastHelper.showToast("无效的手机号码");
        }
    }

    public void authOldPhoneNumber() {
        String oldPhone = getToValue("oldPhone", "");
        if(phoneIsValid(oldPhone)) {
            bindGuideService.authPhoneNumberBy(oldPhone);
        } else {
            ToastHelper.showToast("无效的手机号码");
        }
    }

    /** 获取验证码 */
    public void fetchVerificationCode() {
        startCountDown();
        requestVerifyCode1Focus();
        bindGuideService.fetchVerificationCode(bindPhoneNumber());
    }

    /** 校验验证码 */
    public void checkVerificationCode() {
        if(verifyCodeIsValid()) {
            bindGuideService.checkVerificationCode(bindPhoneNumber(), verifyCode());
        } else {
            ToastHelper.showToast("无效的验证码");
        }
    }

    public void replaceBindMobile() {
        if(verifyCodeIsValid()) {
            bindGuideService.replaceBindMobile(getToValue("newPhone"), verifyCode());
        } else {
            ToastHelper.showToast("无效的验证码");
        }
    }

    public void artificialReplaceMobile() {
        String phoneNumber = getToValue("newPhone");
        String contactInfo = getToValue("contactPhone", "");
        String appointmentTime = getToValue("contactTime", "");
        String reason = getToValue("note", "");
        bindGuideService.artificialReplaceMobile(phoneNumber, contactInfo, appointmentTime, reason);
    }
    //endregion #业务与数据 end

    //region    #对话框弹窗 begin
    public void showExistBindDialog() {
        String newPhone = getToValue("newPhone", "");
        DialogFastBuildUtil.builder(R.layout.dialog_common_prompt_light_l)
                .setTextView(R.id.dialog_title, "无法完成绑定")
                .setTextView(R.id.dialog_content, String.format("该手机号已经被使用，是否将\n“%s”与当前账号关联", newPhone))
                .setTextView(R.id.dialog_button_light, "关联账号", confirmView -> {
                    AntsRouter.ROUTER.buildCard(Navigation.Page.AccountsAssociatedPage).navigation();
                    DialogFastBuildUtil.dismissDialogBy(confirmView);
                })
                .setTextView(R.id.dialog_button_dark, "使用其他手机号", DialogFastBuildUtil::dismissDialogBy)
                .show();
    }
    //endregion #对话框弹窗 end

    //region    #面板操作 begin
    private final Stack<AccountBusinessPanelLayout> pageStack = new Stack<>();
    private AccountBusinessPanelLayout currentPanelLayout = null;

    public void initPanelLayout() {
        pageStack.clear();
        set("newPhone", "");
        set("oldPhone", "");
        set("bindPhoneNumberHint", String.format("当前绑定手机号:%s", StringUtil.replace("****", UserEntity.self.getMobile(), 3)));
        refreshSubmitBtnUI("", "", "");

        if(UserEntity.self.haveBindMobile()) {
            AccountBusinessPanelLayout.NewPhoneVerify.addNext(AccountBusinessPanelLayout.CodeVerify);
            AccountBusinessPanelLayout.PhoneVerifyWay.addNext(AccountBusinessPanelLayout.CodeVerify);
            AccountBusinessPanelLayout.ChangePhoneWay.addNext(AccountBusinessPanelLayout.PhoneVerifyWay);
            gotoPage(AccountBusinessPanelLayout.ChangePhoneWay);
        } else {
            AccountBusinessPanelLayout.CodeVerify.addNext(AccountBusinessPanelLayout.BindGuideFinishHint);
            AccountBusinessPanelLayout.NewPhoneVerify.addNext(AccountBusinessPanelLayout.CodeVerify);
            gotoPage(AccountBusinessPanelLayout.NewPhoneVerify);
        }
    }

    /**
     * 返回上一个面板，如果是顶层结束面板则直接返回 true；
     * @return 如果当前面板不是顶层结束面板则返回false，否则返回true。
     */
    public boolean backPanel() {
        if(ListUtil.isEmpty(pageStack) || currentPanelLayout.isFinish) {
            return true;
        }
        refreshPage(pageStack.pop());
        return false;
    }

    public void nextPage() {
        if(currentPanelLayout == null)
            return;
        if(currentPanelLayout.next() == null) {
//            activity.finish();
            return;
        }
        if(currentPanelLayout.needRecycle()) {
            pageStack.push(currentPanelLayout);
        }
        refreshPage(currentPanelLayout.next());
    }

    public void gotoPage(AccountBusinessPanelLayout page) {
        if(currentPanelLayout != null) {
            pageStack.push(currentPanelLayout);
        }
        refreshPage(page);
    }

    private void refreshPage(AccountBusinessPanelLayout page) {
        this.currentPanelLayout = page;
        resetVerifyCode();

        int[] layoutVisible = new int[8];
        Arrays.fill(layoutVisible, View.GONE);
        switch (currentPanelLayout) {
            case ChangePhoneWay:
                layoutVisible[0] = View.VISIBLE; break;
            case PhoneVerifyWay:
                layoutVisible[1] = View.VISIBLE; break;
            case NewPhoneVerify:
                layoutVisible[2] = View.VISIBLE; break;
            case CodeVerify:
                layoutVisible[3] = View.VISIBLE; break;
            case OldPhoneVerify:
                layoutVisible[4] = View.VISIBLE; break;
            case ChangePhoneByAppeal:
                layoutVisible[5] = View.VISIBLE; break;
            case Waiting:
                layoutVisible[6] = View.VISIBLE; break;
            case BindGuideFinishHint:
                layoutVisible[7] = View.VISIBLE; break;
        }

        set("layoutVisible", layoutVisible);
        set("title", currentPanelLayout != null ? currentPanelLayout.pageTitle : "手机号绑定");
    }

    //endregion #面板操作 end

    //region    #关联更新 begin
    @PropertyObserve(name = "newPhone")
    public void onNewPhoneChange(String newPhone) {
        boolean newPhoneIsValid = phoneIsValid(newPhone);
        set("newPhoneVerifyButtonEnabled", newPhoneIsValid);
        set("newPhoneVerifyButtonTextColor", newPhoneIsValid ? "#423300" : "#aeaeae");
        set("newPhoneVerifyButtonBackground", newPhoneIsValid ?  R.drawable.app_common_button_yellow : R.drawable.app_account_bind_bg_gray);
    }

    @PropertyObserve(name = "oldPhone")
    public void onOldPhoneChange(String oldPhone) {
        boolean oldPhoneIsValid = phoneIsValid(oldPhone);
        set("oldPhoneVerifyButtonEnabled", oldPhoneIsValid);
        set("oldPhoneVerifyButtonTextColor", oldPhoneIsValid ? "#423300" : "#aeaeae");
        set("oldPhoneVerifyButtonBackground", oldPhoneIsValid ?  R.drawable.app_common_button_yellow : R.drawable.app_account_bind_bg_gray);
    }

    @PropertyObserve(name = "contactPhone")
    public void onContactPhoneChange(String contactPhone) {
        String contactTime = getToValue("contactTime", "");
        String note = getToValue("note", "");
        refreshSubmitBtnUI(contactPhone, contactTime, note);
    }
    @PropertyObserve(name = "contactTime")
    public void onContactTimeChange(String contactTime) {
        String contactPhone = getToValue("contactPhone", "");
        String note = getToValue("note", "");
        refreshSubmitBtnUI(contactPhone, contactTime, note);
    }
    @PropertyObserve(name = "note")
    public void onNoteChange(String note) {
        String contactPhone = getToValue("contactPhone", "");
        String contactTime = getToValue("contactTime", "");
        refreshSubmitBtnUI(contactPhone, contactTime, note);
    }
    private void refreshSubmitBtnUI(String contactPhone, String contactTime, String note) {
        boolean appealInfoIsValid = appealInfoIsValid(contactPhone, contactTime, note);
        set("submitBtnEnabled", appealInfoIsValid);
        set("submitBtnTextColor", appealInfoIsValid ? "#423300" : "#aeaeae");
        set("submitBtnBackground", appealInfoIsValid ?  R.drawable.app_common_button_yellow : R.drawable.app_account_bind_bg_gray);
    }

    //endregion #关联更新 end

    //region    #验证码操作 begin
    private int verifyCode1 = -1;
    private int verifyCode2 = -1;
    private int verifyCode3 = -1;
    private int verifyCode4 = -1;

    /** 验证码计时器*/
    private CountDownTimer timer;

    public void requestVerifyCode1Focus() {
        final EditText focusView = viewDataBinder.verifyCode1;
        focusView.requestFocus();
        focusView.postDelayed(()-> UIUtil.showKeyboard(focusView.getContext(), focusView), 300);
    }

    /** 获取验证码倒计时*/
    private void startCountDown() {
        if(ObjectUtil.nonNull(timer)) {
            timer.cancel();
            timer.onFinish();
        }

        setFetchVerifyCodeTextEnabled(false);
        timer = CountDownTimerBuilder.build(60, 1, TimeUnit.SECONDS)
                .addTickCallBack((countDownTime, timeUnit) -> {
                    setFetchVerifyCodeText(String.format("重新获取(%ss)", countDownTime--));
                    return countDownTime;
                })
                .addFinishCallBack((countDownTime, timeUnit) -> {
                    resetGetCodeButton();
                    return countDownTime;
                }).start();
    }
    /** 恢复获取验证码按钮*/
    public void resetGetCodeButton() {
        if(ObjectUtil.nonNull(timer)) {
            timer.cancel();
        }
        setFetchVerifyCodeText("重新获取");
        setFetchVerifyCodeTextEnabled(true);
    }

    private void setFetchVerifyCodeText(CharSequence fetchVerifyCodeText) {
        set("fetchVerifyCodeText", fetchVerifyCodeText);
    }

    private void setFetchVerifyCodeTextEnabled(boolean fetchVerifyCodeTextEnabled) {
        set("fetchVerifyCodeTextColor", fetchVerifyCodeTextEnabled ? "#ff9204" : "#aeaeae");
        set("fetchVerifyCodeTextEnabled", fetchVerifyCodeTextEnabled);
    }

    private void resetVerifyCode() {
        set("verifyCode1", "");
        set("verifyCode2", "");
        set("verifyCode3", "");
        set("verifyCode4", "");
        resetGetCodeButton();

        String coverNumber = StringUtil.replace("****", bindPhoneNumber(), 3);
        set("phoneNumberHint", coverNumber);
    }

    private String verifyCode() {
        return String.format("%s%s%s%s", verifyCode1, verifyCode2, verifyCode3, verifyCode4);
    }

    private boolean verifyCodeIsValid() {
        return verifyCode1 >= 0 && verifyCode2 >= 0 && verifyCode3 >= 0 && verifyCode4 >= 0;
    }

    /**
     * 刷新验证码确认按钮状态
     */
    private void refreshVerifyBtn() {
        put("verifyBtnEnabled", verifyCodeIsValid());
        put("verifyBtnTextColor", verifyCodeIsValid() ? "#423300" : "#aeaeae");
        put("verifyBtnBackground", verifyCodeIsValid() ? R.drawable.app_accounts_associated_bg_yellow : R.drawable.app_accounts_associated_bg_gray);
    }

    /**
     * 以下是4个验证码输入框的状态监听，如果输入框内容发生改变则会触发观察者消息
     */
    @PropertyObserve(name = "verifyCode1")
    public void setVerifyCode1(String verifyCode1) {
        try {
            int codeValue = Integer.valueOf(verifyCode1);
            // 解决光标位置问题导致可能最新输入的字符在旧字符前需要判断故做一下数值运算处理，始终使用最新值替换旧值；
            if(codeValue != this.verifyCode1 || verifyCode1.length() > 1) {
                this.verifyCode1 = codeValue % 10 == this.verifyCode1 ? codeValue / 10 : codeValue % 10;
                set("verifyCode1", String.valueOf(this.verifyCode1));
            }
            viewDataBinder.verifyCode2.requestFocus();
        } catch(Exception e) {
            this.verifyCode1 = -1;
        }
        refreshVerifyBtn();
    }
    @PropertyObserve(name = "verifyCode2")
    public void setVerifyCode2(String verifyCode2) {
        try {
            int codeValue = Integer.valueOf(verifyCode2);
            if(codeValue != this.verifyCode2 || verifyCode2.length() > 1) {
                this.verifyCode2 = codeValue % 10 == this.verifyCode2 ? codeValue / 10 : codeValue % 10;
                set("verifyCode2", String.valueOf(this.verifyCode2));
            }
            viewDataBinder.verifyCode3.requestFocus();
        } catch(Exception e) {
            this.verifyCode2 = -1;
            viewDataBinder.verifyCode1.requestFocus();
        }
        refreshVerifyBtn();
    }
    @PropertyObserve(name = "verifyCode3")
    public void setVerifyCode3(String verifyCode3) {
        try {
            int codeValue = Integer.valueOf(verifyCode3);
            if(codeValue != this.verifyCode3 || verifyCode3.length() > 1) {
                this.verifyCode3 = codeValue % 10 == this.verifyCode3 ? codeValue / 10 : codeValue % 10;
                set("verifyCode3", String.valueOf(this.verifyCode3));
            }
            viewDataBinder.verifyCode4.requestFocus();
        } catch(Exception e) {
            this.verifyCode3 = -1;
            viewDataBinder.verifyCode2.requestFocus();
        }
        refreshVerifyBtn();
    }
    @PropertyObserve(name = "verifyCode4")
    public void setVerifyCode4(String verifyCode4) {
        try {
            int codeValue = Integer.valueOf(verifyCode4);
            if(codeValue != this.verifyCode4 || verifyCode4.length() > 1) {
                this.verifyCode4 = codeValue % 10 == this.verifyCode4 ? codeValue / 10 : codeValue % 10;
                set("verifyCode4", String.valueOf(this.verifyCode4));
            }
        } catch(Exception e) {
            this.verifyCode4 = -1;
            viewDataBinder.verifyCode3.requestFocus();
        }
        refreshVerifyBtn();
    }
    //endregion #验证码操作 end

}